/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gss;

import org.apache.commons.math.fraction.BigFraction;

import java.util.Collection;
import java.util.Vector;
import java.util.HashSet;
import java.util.Set;
import java.util.Iterator;
import java.util.List;
import java.util.Comparator;

/**
 *
 * @author mdm32
 */
public class Vertex {

    private BigFraction xcoord;
    private BigFraction ycoord;
    private Set<LineSegment> visibility;
    //private static final double EPSILON = 0.01;
    /**
     * Compares vertices by x coordinates
     *
     */
    public static class XComparator implements Comparator<Vertex> {

	@Override
	public int compare(Vertex arg0, Vertex arg1) {
	    return arg0.xcoord.compareTo(arg1.xcoord);
	}

    }
    
    /**
     * Compares vertices by y coordinates
     *
     */
    public static class YComparator implements Comparator<Vertex> {

	@Override
	public int compare(Vertex arg0, Vertex arg1) {
	    return arg0.ycoord.compareTo(arg1.ycoord);
	}

    }

   
    public Vertex() {
	visibility = new HashSet<LineSegment>();
        //visibility.add("-1");
        xcoord = new BigFraction(-1);
        ycoord = new BigFraction(-1);
    }

    public Vertex(BigFraction x, BigFraction y) {
	visibility = new HashSet<LineSegment>();
        xcoord = x;
        ycoord = y;
    }

    public Vertex(Set<LineSegment> vis, BigFraction x, BigFraction y) {
        visibility = vis;
        xcoord = x;
        ycoord = y;
    }

    public Vertex(Set<LineSegment> vis, double x, double y) {
        visibility = vis;
        xcoord = new BigFraction(x);
        ycoord = new BigFraction(y);
    }

    public Vertex(double x, double y) {
        visibility = new HashSet<LineSegment>();
        xcoord = new BigFraction(x);
        ycoord = new BigFraction(y);
    }

    public Vertex(LineSegment seg, double x, double y) {
        xcoord = new BigFraction(x);
        ycoord = new BigFraction(y);

        visibility = new HashSet<LineSegment>();
        visibility.add(seg);
    }

    public Vertex(LineSegment seg, BigFraction x, BigFraction y) {
        xcoord = x;
        ycoord = y;

        visibility = new HashSet<LineSegment>();
        visibility.add(seg);
    }

    public BigFraction getX() {
        return xcoord;
    }

    public BigFraction getY() {
        return ycoord;
    }

    public Set<LineSegment> getVisibility() {
	return visibility;
    }

    public void setX(BigFraction x) {
        xcoord = x;
    }

    public void setY(BigFraction y) {
        ycoord = y;
    }

    public void setX(double x) {
        xcoord = new BigFraction(x);
    }

    public void setY(double y) {
        ycoord = new BigFraction(y);
    }

    public void setVisibility(Set<LineSegment> vis) {
        visibility = vis;
    }

    @Override
    public boolean equals(Object a) {
	if (a==null || a.getClass() != this.getClass()) { return false; }
	Vertex v = (Vertex) a;
        if (xcoord.equals(v.xcoord) && ycoord.equals(v.ycoord)) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 79 * hash + (xcoord != null ? xcoord.hashCode() : 0);
        hash = 79 * hash + (ycoord != null ? ycoord.hashCode() : 0);
        return hash;
    }

    public String toString() {
        String str = xcoord.toString() + ", " + ycoord.toString();
        return str;
    }

    /**
     * Generates a string of space separated 0's and 1's representing the
     * row in the adjacency matrix represented by this Vertex. 
     *
     * @param	segments    list of LineSegment's ordered by their
     *			    column position in the adjacency matrix.
     * @return	string of space separated 0's and 1's representing the
     *		adjacency matrix row
     */
    public String toIncidenceMatrixRow(
	    Collection<? extends LineSegment> segments)
    {
	String rowString = "";
	for (LineSegment l : segments) {
	    if (visibility.contains(l)) {
		rowString = rowString + " 1";
	    } else {
		rowString = rowString + " 0";
	    }
	}
	return rowString.trim();
    }

    /**
     * Adds all the segments in the collection to visibility for
     * this vertex.
     *
     * @param	segments    collection of segments to add to visibility
     */
    public void mergeVisibility(Collection<LineSegment> segments) {
	visibility.addAll(segments);
    }

    public double distanceTo(Vertex b) {
        return Math.sqrt(
		(xcoord.doubleValue() - b.getX().doubleValue()) *
		    (xcoord.doubleValue() - b.getX().doubleValue())
		+ (ycoord.doubleValue() - b.getY().doubleValue()) *
		    (ycoord.doubleValue() - b.getY().doubleValue())
		);
    }
}
